import Watcher from "./observe/watcher";
import { createElementVNode, createTextVNode, patch } from "./vdom/index";

/* 生命周期钩子 */
export function initLifeCycle(Vue) {
  // 拿到虚拟dom进行更新，将虚拟dom转成真实dom
  Vue.prototype._update = function (VNode) {
    const vm = this;
    const el = vm.$el;
    // console.log(VNode, el);

    // patch既有初始化的功能，又有更新的逻辑
    vm.$el = patch(el, VNode);
  };

  /* 这几个功能都和虚拟节点diff算法有关 */
  // _c('div',{属性},...children)
  Vue.prototype._c = function () {
    // 额外传入一个vm，即this，用于判断dom对应的实例是谁
    return createElementVNode(this, ...arguments);
  };
  // _v(text)
  Vue.prototype._v = function () {
    // 额外传入一个vm，即this，用于判断dom对应的实例是谁
    return createTextVNode(this, ...arguments);
  };
  // _s(变量)
  Vue.prototype._s = function (value) {
    // 会在this中取值
    if (typeof value !== "object") return value;
    return JSON.stringify(value);
  };

  // 通过ast语法转义后生成的render方法，执行会产生虚拟节点VNode
  // 执行render函数，渲染的时候会去实例中取值，可以将属性和视图绑定到一起
  Vue.prototype._render = function () {
    return this.$options.render.call(this);
  };
}
/* 
    组件的挂载 
    1. 调用render方法产生虚拟节点（虚拟DOM）
    2. 根据虚拟DOM产生真实DOM
    3. 插入到el元素中
*/
export function mountComponent(vm, el) {
  vm.$el = el; // 这里的el是通过document.querySelector拿到的

  // 1. 调用render方法产生虚拟节点（虚拟DOM）
  // const VNode = vm._render();
  // 2. 根据虚拟DOM产生真实DOM
  // 3. 插入到el元素中
  // vm._update(VNode);

  // 传进来的渲染方法
  const updateComponent = () => {
    vm._update(vm._render());
  };
  // debugger;
  const watcher = new Watcher(vm, updateComponent, true); // true用于标识是一个渲染过程
  console.log(watcher);
}
